package edu.ccut.saturn.component.loader;

import java.util.LinkedList;
import java.util.List;

import org.dom4j.Element;
import org.osgi.framework.Bundle;

import edu.ccut.saturn.component.INodeInfo;
import edu.ccut.saturn.component.SaturnComponentException;
import edu.ccut.saturn.component.loader.node.BaseComponentNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.DataMappingNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.DataNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.DecisionNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.EndIterationNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.EndNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.LogicComponentNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.NodeInfoLoader;
import edu.ccut.saturn.component.loader.node.StartIterationNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.StartNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.SubActionComponentNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.SwitchNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.TransactionBeginNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.TransactionCommitNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.TransactionRollBackNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.TransformNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.ViewNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.WebContextNodeInfoLoader;
import edu.ccut.saturn.component.loader.node.WorkFlowNodeInfoLoader;

/**
 * 用于加载组件内部的结点，记录了各个结点的加载类，统一调用。
 * 
 * @author 谷钰
 * 
 * @see INodeInfo
 * @see NodeInfoLoader
 *
 * @version 1.0, 2008.8.23
 */
public abstract class NodeResolver {

	private static final NodeInfoLoader startNodeInfoLoader = new StartNodeInfoLoader();

	private static final NodeInfoLoader decisionNodeInfoLoader = new DecisionNodeInfoLoader();

	private static final NodeInfoLoader baseComponentNodeInfoLoader = new BaseComponentNodeInfoLoader();

	private static final NodeInfoLoader logicComponentNodeInfoLoader = new LogicComponentNodeInfoLoader();

	private static final NodeInfoLoader endNodeInfoLoader = new EndNodeInfoLoader();

	private static final NodeInfoLoader startIterationNodeInfoLoader = new StartIterationNodeInfoLoader();

	private static final NodeInfoLoader endIterationNodeInfoLoader = new EndIterationNodeInfoLoader();

	private static final NodeInfoLoader transactionBeginNodeInfoLoader = new TransactionBeginNodeInfoLoader();

	private static final NodeInfoLoader transactionCommitNodeInfoLoader = new TransactionCommitNodeInfoLoader();

	private static final NodeInfoLoader transactionRollBackNodeInfoLoader = new TransactionRollBackNodeInfoLoader();

	private static final NodeInfoLoader viewNodeInfoLoader = new ViewNodeInfoLoader();

	private static final NodeInfoLoader dataNodeInfoLoader = new DataNodeInfoLoader();

	private static final NodeInfoLoader transformNodeInfoLoader = new TransformNodeInfoLoader();

	private static final NodeInfoLoader actionComponentNodeInfoLoader = new SubActionComponentNodeInfoLoader();

	private static final NodeInfoLoader webContextNodeInfoLoader = new WebContextNodeInfoLoader();

	private static final NodeInfoLoader dataMappingNodeInfoLoader = new DataMappingNodeInfoLoader();

	private static final NodeInfoLoader workFlowNodeInfoLoader = new WorkFlowNodeInfoLoader();

	private static final NodeInfoLoader switchNodeInfoLoader = new SwitchNodeInfoLoader();
	
	/**
	 * 加载结点信息的方法。循环调用结点加载类的loadNode方法加载结点信息。
	 * 
	 * @param root
	 * @param bundle
	 * @param loaders
	 * @return
	 * @throws SaturnComponentException
	 */
	public static List<INodeInfo> loadNodes(Element root, Bundle bundle,
			NodeInfoLoader[] loaders) throws SaturnComponentException {

		List<INodeInfo> nodes = new LinkedList<INodeInfo>();

		for (NodeInfoLoader loader : loaders) {
			nodes.addAll(loader.loadNode(root, bundle));
		}

		return nodes;
	}

	/**
	 * 加载logic组件内部的结点信息
	 * 
	 * @param root
	 * @param bundle
	 * @return
	 * @throws SaturnComponentException
	 */
	public static List<INodeInfo> loadLogicComponentNodes(Element root,
			Bundle bundle) throws SaturnComponentException {

		return NodeResolver.loadNodes(root, bundle, new NodeInfoLoader[] {
				baseComponentNodeInfoLoader, decisionNodeInfoLoader,
				logicComponentNodeInfoLoader, endNodeInfoLoader,
				startIterationNodeInfoLoader, endIterationNodeInfoLoader,
				transactionBeginNodeInfoLoader,
				transactionCommitNodeInfoLoader,
				transactionRollBackNodeInfoLoader, dataMappingNodeInfoLoader,
				workFlowNodeInfoLoader, switchNodeInfoLoader});
	}

	/**
	 * 加载action组件内部的结点信息
	 * 
	 * @param root
	 * @param bundle
	 * @return
	 * @throws SaturnComponentException
	 */
	public static List<INodeInfo> loadActionComponentNodes(Element root,
			Bundle bundle) throws SaturnComponentException {

		return NodeResolver.loadNodes(root, bundle, new NodeInfoLoader[] {
				decisionNodeInfoLoader, logicComponentNodeInfoLoader,
				viewNodeInfoLoader, dataNodeInfoLoader,
				transformNodeInfoLoader, actionComponentNodeInfoLoader,
				webContextNodeInfoLoader });
	}

	/**
	 * 加载开始结点
	 * 
	 * @param bundle
	 * @param root
	 * @return
	 * @throws SaturnComponentException
	 */
	public static INodeInfo getStartNodeInfo(Bundle bundle, Element root)
			throws SaturnComponentException {

		List<INodeInfo> startNodes = startNodeInfoLoader.loadNode(root, bundle);
		if (startNodes != null && startNodes.size() == 1) {
			INodeInfo startNode = startNodes.get(0);
			return startNode;
		
		} else {
			throw new SaturnComponentException(
					"start node not have or have more");
		}
	}
}
